package com.koi.system.controller.dicttype;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.koi.common.anno.KoiLog;
import com.koi.common.constants.KoiCacheConstants;
import com.koi.common.constants.KoiConstants;
import com.koi.common.enums.log.OperType;
import com.koi.common.ex.koi.YUtil;
import com.koi.common.redis.RedisUtil;
import com.koi.common.satoken.KoiLoginUtil;
import com.koi.model.vo.system.SysDictTypeVo;
import com.koi.pojo.system.SysDictData;
import com.koi.pojo.system.SysDictType;
import com.koi.system.service.dictdata.SysDictDataService;
import com.koi.system.service.dicttype.SysDictTypeService;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.List;

/**
 * @author ･ᴗ･
 * @description [字典类型表-控制层]
 */
@Validated
@RequestMapping("/koi")
@RequiredArgsConstructor
@RestController
public class SysDictTypeController {

    private final SysDictTypeService sysDictTypeService;

    private final SysDictDataService sysDictDataService;

    private final RedisUtil redisUtil;

    /**
     * @description [分页查询]
     * @author ･ᴗ･
     */
    @SaCheckPermission("system:dict:list")
    @GetMapping("/sysDictType/listPage")
    public IPage<SysDictType> listPage(SysDictTypeVo vo) {
        // 分页构造器
        Page<SysDictType> page = new Page<>(vo.getPageNo(), vo.getPageSize());
        // 条件构造器
        LambdaQueryWrapper<SysDictType> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(vo.getDictName()), SysDictType::getDictName, vo.getDictName());
        wrapper.like(StringUtils.isNotBlank(vo.getDictType()), SysDictType::getDictType, vo.getDictType());
        wrapper.eq(StringUtils.isNotBlank(vo.getDictStatus()), SysDictType::getDictStatus, vo.getDictStatus());
        wrapper.orderByDesc(SysDictType::getCreateTime);
        // 进行分页查询
        page = sysDictTypeService.page(page, wrapper);
        return page;
    }

    /**
     * @description [查询所有]
     * @author ･ᴗ･
     */
    @GetMapping("/sysDictType/list")
    public List<SysDictType> list() {
        return sysDictTypeService.list();
    }

    /**
     * @description [根据主键查询]
     * @author ･ᴗ･
     */
    @GetMapping("/sysDictType/getById/{id}")
    public SysDictType getById(@PathVariable Long id) {
        return sysDictTypeService.getById(id);
    }

    /**
     * @description [新增]
     * @author ･ᴗ･
     */
    @KoiLog(title = "新增字典", operType = OperType.ADD)
    @SaCheckPermission("system:dict:add")
    @PostMapping("/sysDictType/add")
    public void add(@Validated @RequestBody SysDictType sysDictType) {
        // 查询是否已经存在字典名称
        LambdaQueryWrapper<SysDictType> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDictType::getDictType, sysDictType.getDictType());
        long count = sysDictTypeService.count(wrapper);
        YUtil.isTrue(count > 0, "该字典类型已存在，请重新输入");
        if (StringUtils.isNotBlank(KoiLoginUtil.getUserName())) {
            sysDictType.setCreateBy(KoiLoginUtil.getUserName());
        }
        YUtil.isTrue(!sysDictTypeService.save(sysDictType), "新增失败，请稍后重试");
        // 同步缓存
        sysDictDataService.listDictCacheRedis();
    }

    /**
     * @description [修改]
     * @author ･ᴗ･
     */
    @KoiLog(title = "修改字典", operType = OperType.UPDATE)
    @SaCheckPermission("system:dict:update")
    @PostMapping("/sysDictType/update")
    public void update(@Validated @RequestBody SysDictType sysDictType) {
        // 根据ID进行查询，用来同步修改字典数据类型
        SysDictType sysDictTypeModel = sysDictTypeService.getById(sysDictType.getDictId());
        // 查询是否已经存在字典名称
        LambdaQueryWrapper<SysDictType> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDictType::getDictType, sysDictType.getDictType());
        SysDictType dictType = sysDictTypeService.getOne(wrapper);
        YUtil.isTrue(ObjectUtils.isNotEmpty(dictType) && !dictType.getDictId().equals(sysDictType.getDictId()), "该字典类型已存在，请重新输入");
        if (StringUtils.isNotBlank(KoiLoginUtil.getUserName())) {
            sysDictType.setUpdateBy(KoiLoginUtil.getUserName());
        }
        YUtil.isTrue(!sysDictTypeService.updateById(sysDictType), "修改失败，请稍后重试");
        if(!sysDictTypeModel.getDictType().equals(sysDictType.getDictType())) {
            // 将字典数据的类型也同步修改
            LambdaUpdateWrapper<SysDictData> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(SysDictData::getDictType, sysDictType.getDictType());
            updateWrapper.eq(SysDictData::getDictType, sysDictTypeModel.getDictType());
            boolean update = sysDictDataService.update(updateWrapper);
            YUtil.isTrue(!update, "修改失败，请稍后重试");
        }
        // 同步缓存
        sysDictDataService.listDictCacheRedis();
    }

    /**
     * @description [删除]
     * @author ･ᴗ･
     */
    @KoiLog(title = "删除字典", operType = OperType.DELETE)
    @SaCheckPermission("system:dict:delete")
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/sysDictType/deleteById/{id}")
    public void delete(@PathVariable("id") Long id) {
        SysDictType sysDictType = sysDictTypeService.getById(id);
        YUtil.isTrue(ObjectUtils.isEmpty(sysDictType) || StringUtils.isBlank(sysDictType.getDictType()), "请检查该数据是否存在");
        LambdaQueryWrapper<SysDictData> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDictData::getDictType, sysDictType.getDictType());
        // 删除字典详情
        sysDictDataService.remove(wrapper);
        YUtil.isTrue(!sysDictTypeService.removeById(id), "删除失败，请稍后重试");
        // 删除缓存
        redisUtil.deleteKey(KoiCacheConstants.DICT_REDIS_KEY + sysDictType.getDictType());
        // 同步缓存
        sysDictDataService.listDictCacheRedis();
    }

    /**
     * @description [批量删除]
     * @author ･ᴗ･
     */
    @KoiLog(title = "批量删除字典", operType = OperType.DELETE)
    @SaCheckPermission("system:dict:delete")
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/sysDictType/batchDelete")
    public void batchDelete(@NotNull(message = "请选择需要删除的数据") @RequestBody List<Long> ids) {
        if (CollectionUtil.isNotEmpty(ids)) {
            for (Long id : ids) {
                SysDictType sysDictType = sysDictTypeService.getById(id);
                YUtil.isTrue(ObjectUtils.isEmpty(sysDictType) || StringUtils.isBlank(sysDictType.getDictType()), "请检查该数据是否存在");
                LambdaQueryWrapper<SysDictData> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(SysDictData::getDictType, sysDictType.getDictType());
                YUtil.isTrue(!sysDictDataService.remove(wrapper), "删除失败，请稍后重试");
                // 删除缓存
                redisUtil.deleteKey(KoiCacheConstants.DICT_REDIS_KEY + sysDictType.getDictType());
            }
        }
        YUtil.isTrue(!sysDictTypeService.removeBatchByIds(ids), "批量删除失败，请稍后重试");
        // 同步缓存
        sysDictDataService.listDictCacheRedis();
    }

    /**
     * @description [修改状态]
     * @author ･ᴗ･
     */
    @SaCheckPermission("system:dict:update")
    @PostMapping("/sysDictType/updateStatus/{dictId}/{dictStatus}")
    public void updateStatus(@PathVariable("dictId") Long dictId, @PathVariable("dictStatus") String dictStatus) {
        UpdateWrapper<SysDictType> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("dict_status", dictStatus).eq("dict_id", dictId);
        YUtil.isTrue(!sysDictTypeService.update(null, updateWrapper), "修改失败，请稍后重试");
        // 同步缓存
        sysDictDataService.listDictCacheRedis();
    }

    /**
     * @description [查询字典类型下拉框]
     * @author ･ᴗ･
     */
    @GetMapping("/sysDictType/listDictType")
    public List<SysDictType> listDictType() {
        LambdaQueryWrapper<SysDictType> wrapper = new LambdaQueryWrapper<>();
        // 按需加载
        wrapper.select(SysDictType::getDictType, SysDictType::getDictName);
        wrapper.eq(SysDictType::getDictStatus, KoiConstants.ZERO_STRING);
        List<SysDictType> dictTypeList = sysDictTypeService.list(wrapper);
        if (CollectionUtils.isNotEmpty(dictTypeList)) {
            return dictTypeList;
        } else {
            return Collections.emptyList();
        }
    }

}
